package cn.edu.jlu.community.server;


import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.widget.Toast;

import com.avos.avoscloud.AVException;
import com.avos.avoscloud.AVFile;
import com.avos.avoscloud.AVOSCloud;
import com.avos.avoscloud.AVObject;
import com.avos.avoscloud.AVQuery;
import com.avos.avoscloud.AVUser;
import com.avos.avoscloud.FindCallback;
import com.avos.avoscloud.GetCallback;
import com.avos.avoscloud.GetDataCallback;
import com.avos.avoscloud.LogInCallback;
import com.avos.avoscloud.SaveCallback;
import com.avos.avoscloud.SignUpCallback;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.edu.jlu.community.util.Log;
import cn.edu.jlu.community.util.ToastUtil;

public class AppServer {

    private static final String APP_ID = "rxch0casmprdu80sewclfo2wqprpzl7l78d9opj5fqc98ldf";
    private static final String CLIENT_KEY = "039uwk8vmi35xb2ck850hya4y154gm78vsf27gvwc8i9s9ss";

    public final static int FORUM_CATEGORY = 1;
    public final static int NOTIFICATION_CATEGORY = 2;
    public final static int NEWS_CATEGORY = 3;

    public static void init(Context context) {
        AVOSCloud.initialize(context, APP_ID, CLIENT_KEY);

        AVOSCloud.setLastModifyEnabled(true);
    }

    public static void signIn(String username, String password, LogInCallback<AVUser> signInCallback) {
        AVUser.logInInBackground(username, password, signInCallback);
    }

    public static void signUp(String username, String password, SignUpCallback signUpCallback) {
        AVUser user = new AVUser();
        user.setUsername(username);
        user.setPassword(password);
        user.signUpInBackground(signUpCallback);
    }

    public static void signOut() {
        AVUser.logOut();
    }

    public interface LoaderCallback {
        public void onFinish(Object data);

        public void onError(AVException e);
    }

    public static void loadPortraitUrl(String id, final LoaderCallback callback) {
        AVQuery<AVUser> query = AVQuery.getQuery(AVUser.class);
        query.include("portrait");

        query.getInBackground(id, new GetCallback<AVUser>() {
            @Override
            public void done(AVUser avUser, AVException e) {
                if (null == e) {
                    AVFile portrait = (AVFile) avUser.get("portrait");
                    callback.onFinish(portrait);
                } else {
                    Log.e(e.getMessage());
                    callback.onError(e);
                }
            }
        });
    }

    public static void loadPortrait(String id, final LoaderCallback callback) {
        loadPortraitUrl(id, new PortraitCallback(callback));
    }

    private static class PortraitCallback implements LoaderCallback {

        private LoaderCallback mCallback;

        PortraitCallback(LoaderCallback callback) {
            mCallback = callback;
        }

        @Override
        public void onFinish(Object data) {
            if (null != data) {
                ((AVFile) data).getDataInBackground(new GetDataCallback() {
                    @Override
                    public void done(byte[] bytes, AVException e) {
                        if (null == e && null != bytes) {
                            Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
                            mCallback.onFinish(bitmap);
                        } else {
                            Log.e(e.getMessage());
                            mCallback.onError(e);
                        }
                    }
                });
            } else {
                mCallback.onError(null);
            }
        }

        @Override
        public void onError(AVException e) {
        }
    }

    public static void loadPostList(final LoaderCallback callback) {
        loadDataByCategory(FORUM_CATEGORY, callback);
    }

    public static void loadNotifications(final LoaderCallback callback) {
        loadDataByCategory(NOTIFICATION_CATEGORY, callback);
    }

    public static void loadNews(final LoaderCallback callback) {
        loadDataByCategory(NEWS_CATEGORY, callback);
    }

    public static void loadDataByCategory(int category, final LoaderCallback callback) {
        AVQuery<AVObject> query = new AVQuery<>("Post");
        query.setCachePolicy(AVQuery.CachePolicy.NETWORK_ELSE_CACHE);
        query.whereEqualTo("category", category).include("from").orderByDescending("updatedAt");

        query.findInBackground(new FindCallback<AVObject>() {
            @Override
            public void done(List<AVObject> objects, AVException e) {
                if (null == e) {
                    List<Map<String, Object>> data = new ArrayList<>();
                    for (AVObject element : objects) {
                        Map<String, Object> map = new HashMap<>();
                        map.put("title", element.get("title"));
                        map.put("objId", element.getObjectId());
                        map.put("author", ((AVUser) element.get("from")).getUsername());
                        map.put("author_id", ((AVUser) element.get("from")).getObjectId());
                        map.put("content", element.get("content"));
                        map.put("comment_count", element.get("commentCount"));
                        map.put("time", element.getUpdatedAt());

                        data.add(map);
                    }
                    callback.onFinish(data);
                } else {
                    Log.e(e.getMessage());
                    callback.onError(e);
                }
            }
        });
    }

    public static void loadComment(String id, final LoaderCallback callback) {
        AVQuery<AVObject> queryPost = new AVQuery<>("Post");
        queryPost.setCachePolicy(AVQuery.CachePolicy.NETWORK_ELSE_CACHE);

        queryPost.getInBackground(id, new GetCallback<AVObject>() {
            @Override
            public void done(AVObject tempPost, AVException e) {
                if (null == e) {
                    AVQuery<AVObject> queryComment = AVQuery.getQuery("Comment");
                    queryComment.whereEqualTo("post", tempPost).include("from");
                    queryComment.findInBackground(new FindCallback<AVObject>() {
                        public void done(List<AVObject> commentList, AVException e) {
                            // commentList now has the comments for myPost
                            if (null == e) {
                                callback.onFinish(commentList);
                            } else {
                                Log.e(e.getMessage(), e);
                                callback.onError(e);
                            }
                        }
                    });
                } else {
                    Log.e(e.getMessage(), e);
                    callback.onError(e);
                }
            }
        });
    }

    public static void loadDataWithImageByCategory(int category, final LoaderCallback callback) {

        AVQuery<AVObject> query = new AVQuery<>("Post");
        query.setCachePolicy(AVQuery.CachePolicy.CACHE_THEN_NETWORK);
        query.whereEqualTo("category", category).whereNotEqualTo("drawing", null)
                .setLimit(5).include("drawing").include("from").orderByDescending("updatedAt");

        query.findInBackground(new FindCallback<AVObject>() {
            @Override
            public void done(List<AVObject> avObjects, AVException e) {
                if (null == e) {
                    callback.onFinish(avObjects);
                } else {
                    Log.e(e.getMessage(), e);
                    callback.onError(e);
                }
            }
        });
    }

    public interface PushCallback {
        public void onSuccess();
    }

    public static void newComment(String comment, final String postId, final PushCallback callback) {
        AVObject myComment = new AVObject("Comment");
        myComment.put("content", comment);
        myComment.put("from", AVUser.getCurrentUser());
        myComment.put("post", AVObject.createWithoutData("Post", postId));  //数据关联
        myComment.saveInBackground(new SaveCallback() {
            @Override
            public void done(AVException e) {
                if (null == e) {
                    AVQuery<AVObject> query = new AVQuery<AVObject>("Post");
                    query.whereEqualTo("objectId", postId);
                    query.findInBackground(new FindCallback<AVObject>() {
                        @Override
                        public void done(List<AVObject> posts, AVException e) {
                            if (e == null) {
                                posts.get(0).increment("commentCount");
                                posts.get(0).saveInBackground();
                            }
                        }
                    });
                    callback.onSuccess();
                } else {
                    // Failure
                    ToastUtil.showText("评论失败");
                }
            }
        });
    }

    public static void newPost(String title, String content, final PushCallback callback) {
        AVObject post = new AVObject("Post");
        post.put("title", title);
        post.put("content", content);
        post.put("from", AVUser.getCurrentUser());
        post.put("category", FORUM_CATEGORY);
        post.put("commentCount", 0);
        post.saveInBackground(new SaveCallback() {
            @Override
            public void done(AVException e) {
                if (e == null) {
                    callback.onSuccess();
                } else {
                    // Failure
                }
            }
        });
    }
}
